package com.bsj.power.sdk.util;

import cn.hutool.core.io.FileUtil;
import com.bsj.power.common.util.ExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;

import java.io.File;

/**
 * @author yinhao
 * @version 1.0
 * @description 视频转换类
 * @date 2024/8/23
 */
@Slf4j
public class VideoConvertUtil {

    /**
     * 视频格式转换
     * @param inputFile 代转换视频文件地址
     * @param outputFile 转换完成后文件地址
     * @return
     * @throws Exception
     */
    public static boolean convert(String inputFile, String outputFile) throws Exception {
        long size = FileUtil.size(new File(inputFile));
        if (size == 0) {
            log.warn("文件大小为0，无需转码: {}", inputFile);
            return false;
        }
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        Frame captured_frame;
        FFmpegFrameRecorder recorder = null;

        try {
            grabber.start();

            String videoCodecName = grabber.getVideoCodecName();
            log.info("videoCodecName:{}",videoCodecName);
            //if("h264".equals(videoCodecName)){
            //    log.info("MP4格式视频忽略转换");
            //    return true;
            //}

            recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
//            recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFormat("mp4");
            recorder.setFrameRate(grabber.getFrameRate());
            recorder.setSampleRate(grabber.getSampleRate());
//            recorder.setVideoBitrate(grabber.getVideoBitrate());
            recorder.setVideoBitrate(2000000);
            recorder.setAspectRatio(grabber.getAspectRatio());
            recorder.setAudioBitrate(grabber.getAudioBitrate());
            recorder.setAudioOptions(grabber.getAudioOptions());
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);

            //设置零延迟
            recorder.setVideoOption("tune", "fastdecode");
            // 快速
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("threads", "12");
            recorder.setVideoOption("vsync", "2");

            recorder.start();

            while (true) {
                captured_frame = grabber.grabFrame();
                if (captured_frame == null) {
                    log.info("转码完成");
                    break;
                }
                recorder.record(captured_frame);
            }

            return true;
        } catch (FrameRecorder.Exception e) {
            log.error("转码异常:{}", ExceptionUtil.getStackStr(e));
            return false;
        } finally {
            if (recorder != null) {
                try {
                    recorder.close();
                    log.info("recorder.close ---> 关闭");
                } catch (Exception e) {
                    log.error("recorder.close异常:{}", ExceptionUtil.getStackStr(e));
                }
            }

            try {
                grabber.close();
                log.info("frameGrabber.close ---> 关闭");
            } catch (FrameGrabber.Exception e) {
                log.error("frameGrabber.close异常:{}", ExceptionUtil.getStackStr(e));
            }
        }
    }

    /**
     * 转换前端webp格式数据
     * @param inputFile
     * @param outputFile
     * @return
     * @throws Exception
     */
    public static boolean convertWebP(String inputFile, String outputFile) throws Exception {
        long size = FileUtil.size(new File(inputFile));
        if (size == 0) {
            log.warn("文件大小为0，无需转码: {}", inputFile);
            return false;
        }
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        Frame captured_frame;
        FFmpegFrameRecorder recorder = null;

        try {
            grabber.start();

            String videoCodecName = grabber.getVideoCodecName();
            log.info("videoCodecName:{}",videoCodecName);
            //if("h264".equals(videoCodecName)){
            //    log.info("MP4格式视频忽略转换");
            //    return true;
            //}

            recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
//            recorder.setVideoCodec(avcodec.AV_CODEC_ID_VP8);
            recorder.setFormat("mp4");
//            recorder.setFrameRate(grabber.getFrameRate());
            recorder.setFrameRate(10D);
            recorder.setSampleRate(grabber.getSampleRate());
            recorder.setVideoBitrate(2000000);
            recorder.setAspectRatio(grabber.getAspectRatio());
            recorder.setAudioBitrate(grabber.getAudioBitrate());
            recorder.setAudioOptions(grabber.getAudioOptions());
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);

            //设置零延迟
            recorder.setVideoOption("tune", "fastdecode");
            // 快速
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("threads", "12");
            recorder.setVideoOption("vsync", "2");

            recorder.start();

            while (true) {
                captured_frame = grabber.grabFrame();
                if (captured_frame == null) {
                    log.info("转码完成");
                    break;
                }
                recorder.record(captured_frame);
            }

            return true;
        } catch (FrameRecorder.Exception e) {
            log.error("转码异常:{}", ExceptionUtil.getStackStr(e));
            return false;
        } finally {
            if (recorder != null) {
                try {
                    recorder.close();
//                    log.info("recorder.close ---> 关闭");
                } catch (Exception e) {
                    log.error("recorder.close异常:{}", ExceptionUtil.getStackStr(e));
                }
            }

            try {
                grabber.close();
//                log.info("frameGrabber.close ---> 关闭");
            } catch (FrameGrabber.Exception e) {
                log.error("frameGrabber.close异常:{}", ExceptionUtil.getStackStr(e));
            }
        }
    }

    public static void main(String[] args) throws Exception {
//        convert("D:\\Program Files\\hksdk\\1724331771834.h264", "D:\\Program Files\\hksdk\\11.mp4");
        convertWebP("D:\\Program Files\\hksdk\\t5.mp4",
                "D:\\Program Files\\hksdk\\n5.mp4");
    }
}
